
Skt.Room = L.Class.extend({
	
	includes: L.Mixin.Events,
	
	events: ['roomModeratorUpdate','objectAction'],

	initialize: function(id, type, ownerId, roomList){
		
		this._id = Number(id);
		this._type = type;
		this._ownerId = Number(ownerId);
		this._roomList = roomList;
		
		this._objects = {};
		this._background = null;

		this._roomModerator = new Skt.RoomModerator(this);
		this._roomModerator.on('update', this._roomModeratorUpdate, this);
		
		/* set History */
		var self = this;
		var execute = function(cmd) {
			self.execute.call(self, cmd);
		};
		
		var rollback = function(cmd) {
			self.rollback.call(self, cmd);
		};
		
		this._history = new Skt.History(this, execute, rollback);
	},
	
	_roomModeratorUpdate: function(params) {
		var self = this;
		self.fire('roomModeratorUpdate',params);
	},

	addCommand: function(cmd_name,cmd_params) {
		var self = this;
		var command = {};
		switch(cmd_name) {
		case "addObject":
			command = {
				type: "stroke",
				stroke: cmd_params.object
			};
			break;
		case "removeObject":
			command = {
				type: "erase",
				strokeId: cmd_params.objectId
			};
			break;
		case "updateObject":
			var data = cmd_params.data;
			data.id = cmd_params.objectId;
			command = {
				type: "update",
				stroke: data
			};
			break;
		case "replaceObjects":
			var data = cmd_params.data;
			data.id = cmd_params.objectId;
			command = {
				type: "replace",
				stroke: data
			};
			break;
		case "changeStore":
			command = {
				type: "store",
				store: cmd_params.store
			};
			break;
		case "setBackground":
			command = {
				type: "background",
				background: cmd_params.background
			};
			break;
		}
		self._history.addCommand(command);
	},

	/* History callbacks */
	execute: function(command) {
		var self = this;
		switch(command.type) {
		case "strokes":
		case "batch":
		case "summary":
			command.oldStrokes = self.changeStore(command.strokes);
			break;
		case "stroke":
			self.addObject(command.stroke);
			break;
		case "erase":
			command.stroke = self.getObject(command.strokeId);
			self.removeObject(command.strokeId);
			break;
		case "update":
			command.oldStroke = L.Util.extend({},self.getObject(command.stroke.id));
			self.updateObject(command.stroke.id, command.stroke);
			break;
		case "replace":
			command.oldStroke = self.getObject(command.stroke.id);
			self.replaceObject(command.stroke.id, command.stroke);
			break;
		case "store":
			command.oldStore = self.changeStore(command.store);
			break;
		case "background":
			self.setBackground(command.background);
			break;
		}
	},

	rollback: function(command) {
		var self = this;
		switch(command.type) {
		case "strokes":
		case "batch":
		case "summary":
			self.changeStore(command.oldStrokes);
			break;
		case "stroke":
			self.removeObject(command.stroke.id);
			break;
		case "erase":
			self.addObject(command.stroke);
			break;
		case "update":
		case "replace":
			self.replaceObject(command.oldStroke.id, command.oldStroke);  
			break;        
		case "store":
			self.changeStore(command.oldStore);
			break;
		case "background":
			self.setBackground(null);
			break;
		}      
	},

	addObject: function(object) {
		var self = this;
		var id = object.id;
		self._objects[id] = object;
		
		self.fire('objectAction', {
			action_name: 'addObject',
			attr_list: { 'object': object }
		});
	},

	removeObject: function(objectId){
		var self = this;
		if ( self._objects.hasOwnProperty(objectId) ) 
			delete self._objects[objectId]; 
		else
			console.log('[WARNING] L.Map.removeObject intento eliminar un objeto que no existe');

		self.fire('objectAction', {
			action_name: 'removeObject',
			attr_list: { 'objectId': objectId }
		});
	},

	updateObject: function(objectId, data) {
		var self = Skt.Room.findSelf(this);
		var obj = self.getObject(objectId);
		
		if ( obj != null ) {
			for (var key in data) {
				if(data.hasOwnProperty(key))
					obj[key] = data[key];
			}
		}

		self.fire('objectAction', {
			action_name: 'updateObject',
			attr_list:{ 'object': obj }
		});
	},

	replaceObject: function(objectId, data) {
		var self = this;
		data.id = objectId;
		if ( self._objects.hasOwnProperty(objectId) ) {
			self._objects[objectId] = data;
			self.fire('objectAction', {
				action_name: 'updateObject',
				attr_list: { 'objectId': self._objects[objectId] }
			});
		} else {
			console.log("[WARNING] L.Map.replaceObject objeto no existe, se llamara a L.Room.addObject");
			self.addObject(data);
		}
	},

	changeStore: function(store) {
		var self = this;
		self._objects = store;
		self.fire('objectAction',{
			action_name:'reloadObjects',
			attr_list:{}
		});
		return self._objects;
	},
	
	setBackground: function(url) {
		var self = this;
		self._background = url;
		self.fire('objectAction', {
			action_name: 'setBackground',
			attr_list: {background: self._background}
		});
	},

	eachObject: function(fn, context) {
		var self = this;
		for (var key in self._objects) {
			if (self._objects.hasOwnProperty(key))
				fn.call(context, self._objects[key]);
		}
	},

	getObject: function(objId, FName, echoOff) {
		var self = Skt.Room.findSelf(this);
		if (self.hasObject(objId)) {
			return self._objects[objId];
		} else {
			console.log('[WARNING] Skt.Room.getObject, ' + FName + ' no encontro objeto con id: ' + objId);
			return null;
		}
	},
	
	getObjects: function() {
		return this._objects;
	},

	hasObject: function(objId){
		return this._objects.hasOwnProperty(objId);
	},

	getId: function(){
		return this._id;
	},

	getType: function(){
		return this._type;
	},

	getOwnerId: function() {
		return this._ownerId;
	},

	getRoomList: function() {
		return this._roomList;
	},
	
	getRoomModerator: function() {
		return this._roomModerator;
	},

	getHistory: function(){
		return this._history;
	},
	
	getBackground: function() {
		return this._background;
	}

});

Skt.Room.findSelf = function(room) {
	return Skt.sketchpad.findRoomById(room._id);
};
